package org.linlinjava.litemall.admin.web;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.admin.service.AdminBillService;
import org.linlinjava.litemall.admin.service.BillReportService;
import org.linlinjava.litemall.admin.service.BrandInvoiceService;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.validator.Order;
import org.linlinjava.litemall.core.validator.Sort;
import org.linlinjava.litemall.db.domain.LitemallBill;
import org.linlinjava.litemall.db.domain.LitemallBrandInvoice;
import org.linlinjava.litemall.db.service.LitemallBillService;
import org.linlinjava.litemall.db.service.LitemallBrandInvoiceService;
import org.linlinjava.litemall.admin.util.BillConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.swing.filechooser.FileSystemView;
import javax.validation.constraints.NotNull;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * @author: 账单结算
 * @date: 2019/12/7
 * @description:
 */

@RestController
@RequestMapping("/bill")
public class AdminBillController {
    private final Log logger = LogFactory.getLog(AdminBillController.class);
    @Autowired
    private AdminBillService adminBillService;
    @Autowired
    private BillReportService billReportService;
    @Autowired
    private LitemallBillService billService;
    @Autowired
    private BrandInvoiceService brandInvoiceService;
    @Autowired
    private LitemallBrandInvoiceService litemallBrandInvoiceService;



    /**
     * 查:所有结算单。以时间倒序     可更改
     * @param data
     * page	        Inteder	页	        默认1
     * limit	    Inteder	页数	    默认15
     * name	        String	商户名字	    以商户名模糊查询
     * status	    short	状态值	    有需求可改写成List
     * startTime	String	开始时间	    商城上线时间:前端格式yyyy/MM/dd(苹果格式)
     * endTime	    String	结束时间	    默认结束时间是现在
     * @return     结算单状态：1.未结算  2支付:
     *  101 结算单生成，霜林未支付给商户；(下订单后就是)
     *  102 下单未支付财务取消；
     *  103，超时系统自动取消
     *  201 平台支付，商户未确认；
     *  202 结算单，已付款，商家确认；
     *  203 商户未确认，超过时间，系统自动确认。
     */
    @PostMapping("/bills")
    public Object billList(@RequestBody String data,
                           @Sort @RequestParam(defaultValue = "add_time") String sort,
                           @Order @RequestParam(defaultValue = "desc") String content){
        JSONObject jo = JSONObject.parseObject(data);
        String brandName = jo.getString("name");
        Short status = jo.getShort("status");
        String startTime = jo.getString("startTime");
        String endTime = jo.getString("endTime");
        Integer page = jo.getInteger("page");
        Integer limit = jo.getInteger("limit");

        //自定义格式化 把字符串转成时间
        LocalDate endTimeVo = LocalDate.now();
        LocalDate startTimeVo = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
       //如果 结束时间不为空.解析 .  默认结束时间是现在
        if(!StringUtils.isEmpty(endTime)){ endTimeVo = LocalDate.parse(endTime, formatter); }
        //如果开始时间为空...默认为商城项目开始时间  2020. 5.21
        if(StringUtils.isEmpty(startTime) ){ startTimeVo = LocalDate.of(2020, 05, 21); }
        if (null == page || page < 1  ) { page = 1; }
        if (null == limit || limit < 1) { limit = 15; }
        PageInfo<LitemallBill> query = billService.query(brandName, status, startTimeVo, endTimeVo, page, limit, sort, content);
        return ResponseUtil.ok(query);
    }

    /**
     * 在订单complete状态200 确认时，上传图片地址后，更新bill结算单表。不更新给商户的票据单
     * @param data   1billId 2.url:
     * @return
     */
    @Transactional
    @PostMapping("/update")
    public Object updateBill(@RequestBody String data){
        JSONObject jsonObject = JSONObject.parseObject(data);
        Integer billId = jsonObject.getInteger("id");
        String url = jsonObject.getString("url");

        LitemallBill bill = billService.findById(billId);

        if(null == bill.getReceiptUrl()){
            bill.setReceiptUrl(url);
        }else {
            //如果不是空的继续添加。不要覆盖。url_url_url
            bill.setReceiptUrl(bill.getReceiptUrl() +"_"+ url);
        }
        //上传图片改状态  //201 平台支付，商户未确认
        bill.setStatus(BillConstant.STATUS_PAY_UNCONFIRM);
        bill.setAddTime(LocalDate.now());

         billService.updateBill(bill);

        logger.info("新增图片，更新结算单");
        return ResponseUtil.ok();
    }

    /**
     * 给中间商的比例RATE...
     * @param json  id是结算单的billId   rate是0-100 之间的数 给黄牛的比率
     * @return
     */
    @PostMapping("/rate")
    public Object hasScalper(@RequestBody String json){
        BigDecimal IntegerZero = new BigDecimal(0) ;
        BigDecimal IntegerHundred = new BigDecimal(100) ;
        Integer billId = JacksonUtil.parseInteger(json, "id");
        Integer rate = JacksonUtil.parseInteger(json, "rate");
        System.out.println("rate>>>>" + rate);
        if(null == rate || "".equals(rate) ){
            ResponseUtil.badArgumentValue();
            throw  new RuntimeException("请传入0到100之间的数");
        }
        assert rate != null;
        BigDecimal rateBigD = new BigDecimal(rate);
        //比较大小用compareTo() 返回值 -1 小于 0 等于 1 大于
        if( rateBigD.compareTo(IntegerZero)  < 0 || IntegerHundred.compareTo(rateBigD) < 0 ){
            ResponseUtil.badArgumentValue();
            throw  new RuntimeException("请传入0到100之间的数");
        }
        BigDecimal scalperRateBigDecimal = new BigDecimal(rate).divide(IntegerHundred);
        adminBillService.updateBill4ScalperRate(billId, scalperRateBigDecimal);
        return ResponseUtil.ok();
    }


    /**
     * 结算单:平台、商户：营收比例 详细信息    //需要显示8项 其他隐藏
     * 1商户开票=下单者实际支付服务金额	"actualPrice": 10000,
     * 2商户收入                          "brandIncome": 8500
     * 3商户的优惠金额  			"brandCoupon": 0,
     * 4霜林 给 商户开票金额		"invoicePrice": 1500
     * 5霜林 给 减免额                     "couponPrice": 100,
     * 6霜林 收入 				"income": 650,
     * 7中间商 收入  			"scalperPrice": 750,
     * 8中间商
     * @param id
     * @return
     */
    @GetMapping("/detail")
    public Object detail(@NotNull Integer id) {
        LitemallBill bill = billService.findById(id);
        LitemallBill billvo = new LitemallBill();
        //商户开票=实际支付金额
        billvo.setActualPrice( bill.getActualPrice());
        //商户收入
        billvo.setBrandIncome(bill.getBrandIncome());
        //商家优惠
        billvo.setBrandCoupon( bill.getBrandCoupon());
        //平台给商户开票额
        billvo.setInvoicePrice(bill.getInvoicePrice());
        //平台优惠金额
        billvo.setCouponPrice(bill.getCouponPrice());
        //平台收入
        billvo.setIncome(bill.getIncome());
        //中间商收入
        billvo.setScalperPrice(bill.getScalperPrice());
        //客户invitation中间商信息
        billvo.setCustomerInvitation(bill.getCustomerInvitation());

        return  ResponseUtil.ok(billvo);
    }

    /**
     * 结算单:税票详情   结算单ID-->结算单-->票据ID-->票据信息
     * @param data id 是结算单的ID
     * @return 返回票据详情
     */
    @PostMapping("/invoice")
    public Object invoice(@RequestBody String data){
        JSONObject jsonObject = JSONObject.parseObject(data);
        Integer billId = jsonObject.getInteger("id");
        Integer invoiceId = billService.findById(billId).getInvoiceId();
        LitemallBrandInvoice invoice = brandInvoiceService.findInvoiceById(invoiceId);
        return ResponseUtil.ok(invoice);
    }

    /**
     * 商户需要上传税票.确认后:  更新票据信息  ：状态 已提交--200  * 未提交--300
     * @param json  包含:1根据billId确认的 税票ID
     *                  2.url: 上传税票后的 税票地址  3tax 税号
     * @return  修改成功:受影响行数  大等于1
     */
    @Transactional
    @PostMapping("/updateInvoice")
    public Object updateInvoice(@RequestBody String json){
        JSONObject jsonObject = JSONObject.parseObject(json);
        Integer invoiceId = jsonObject.getInteger("id");
        String url = jsonObject.getString("url");
        String tax = jsonObject.getString("tax");
        if(StringUtils.isEmpty(url)){
            throw new  RuntimeException( "请确认发票保存");
        }
        //税号只能为 15  18 20 ..
        if(StringUtils.isNotEmpty(tax)){
            boolean invoiceNoLegal = tax.length() != 15 && tax.length() != 18 && tax.length() != 20;
            if(invoiceNoLegal){
                throw new  RuntimeException( "请确认发票税号位数:15(旧),18(新)或20(特殊)");
            }
        }
        //1ID 2税号 3图片地址//更改票据状态
        int isZero = brandInvoiceService.updateInvoice(invoiceId, tax, url);
        //如果更改成功大于0
        if(isZero > 0 ){
            return ResponseUtil.ok();
        }
        return ResponseUtil.fail();
    }

    /**
     * 显示某个商户所有的   与霜林  的  税票信息
     * @param brandId 商户ID
     * @param page     页
     * @param pageSize  每页条数
     * @return
     */
    @GetMapping("/invoiceList/{brandId}/{page}/{pageSize}")
    public Object invoiceList(@PathVariable("brandId") Integer brandId,@PathVariable("page") Integer page , @PathVariable("pageSize") Integer pageSize){
        PageInfo<LitemallBrandInvoice> brandInvoicePageInfo = litemallBrandInvoiceService.invoiceListByBrandId(brandId, page, pageSize);
        return ResponseUtil.ok(brandInvoicePageInfo);
    }

    /**
     * 生成报表    json中 放入结算单信息 { "bills": [  { 1 },{2},{3} ] }  会在项目相对路径生成  litemall\bill\billReport.xls
     * @param json
     */
    @PostMapping("/creatExcel")
    public Object createBillExcel(@RequestBody String json){
        String excel = billReportService.createExcel(json);
        return ResponseUtil.ok(excel);
    }

    /**
     * 下载报表
     * @param response
     * @return
     * @throws UnsupportedEncodingException
     */
    @GetMapping(value = "/downExcel", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public Object downExcel( HttpServletResponse response) throws UnsupportedEncodingException {

        // //192.144.180.108
        // String filePath = URLDecoder.decode(path, "utf-8").trim();

        String savePath = System.getProperty("user.dir") + "\\bill";
        //获取本地桌面地址 savePath
      /*  FileSystemView fsv = FileSystemView.getFileSystemView();
        File home = fsv.getHomeDirectory();
        String savePath = home.getPath();*/
        String fileNameOld ="\\billReport.xls";

        String filePath = savePath + fileNameOld;

        logger.info("filePath>>>"+filePath);
        File file = new File(filePath);

        String fileName = file.getName();
        if(!file.exists()){
            return  ResponseUtil.fail(402,"文件不存在..请先创建报表") ;
        }
        if (fileName != null) {
            // 如果文件存在，则进行下载
            if (file.exists()) {
                // 配置文件下载
                response.setHeader("content-type", "application/octet-stream");
                response.setContentType("application/octet-stream");
                // 下载文件能正常显示中文
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

                // 实现文件下载
                byte[] buffer = new byte[512];

                FileInputStream fis = null;
                BufferedInputStream bis = null;
                try {
                    fis = new FileInputStream(file);
                    bis = new BufferedInputStream(fis);
                    response.setHeader("Content-Length", fis.available()+"");
                    response.setContentType("application/octet-stream");
                    OutputStream os = response.getOutputStream();

                    int i = bis.read(buffer);
                    while (i != -1) {
                        os.write(buffer, 0, i);
                        i = bis.read(buffer);
                    }
                    logger.info("下载Excel成功!>>>" + fileName);
                } catch (Exception e) {

                    logger.info("下载Excel失败！！！!");
                } finally {
                    if (bis != null) {
                        try {
                            bis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (fis != null) {
                        try {
                            fis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        return  ResponseUtil.ok( "下载Excel文件" + fileName +"成功!") ;

    }
}
